<?php
/**
 * PHPUnit 9.5.28
 */
declare(strict_types=1);

require_once __DIR__ . '/../vendor/autoload.php';

use PHPUnit\Framework\TestCase;
use Cephalopod\Http;
use Cephalopod\HttpTube;

class IdealUnpackingTest extends TestCase
{
    public function testEmptyData()
    {
        $data = '';
        $result = Http::idealUnpacking($data);
        $this->assertEquals(-1, $result['content_length']);
        $this->assertEquals('', $result['unknow_data']);
        $this->assertEquals('', $result['body']);
        $this->assertEquals(-1, $result['more']);
    }

    public function testNoEndOfLine()
    {
        $data = 'Hello';
        $result = Http::idealUnpacking($data);
        $this->assertEquals(-1, $result['content_length']);
        $this->assertEquals($data, $result['unknow_data']);
        $this->assertEquals('', $result['body']);
        $this->assertEquals(-1, $result['more']);
    }

    public function testNoDoubleEndOfLine()
    {
        $data = "Hello\r\nThis is a test message\r\n";
        $result = Http::idealUnpacking($data);
        $this->assertEquals(-1, $result['content_length']);
        $this->assertEquals($data, $result['unknow_data']);
        $this->assertEquals('', $result['body']);
        $this->assertEquals(-1, $result['more']);
    }

    public function testNoContentLength()
    {
        $data = "GET / HTTP/1.1\r\n";
        $data .= "Content-Length: 0";
        $data .= "\r\n\r\n";
        $result = Http::idealUnpacking($data);
        $this->assertEquals(0, $result['content_length']);
        $this->assertEquals('', $result['body']);
        $this->assertEquals('', $result['unknow_data']);
        $this->assertEquals(0, $result['more']);
    }

    public function testNoContentLengthAndHaveUnknowData()
    {
        $data = "GET / HTTP/1.1\r\n";
        $data .= "Content-Length: 0";
        $data .= "\r\n\r\n2";
        $result = Http::idealUnpacking($data);
        $this->assertEquals(0, $result['content_length']);
        $this->assertEquals('', $result['body']);
        $this->assertEquals('2', $result['unknow_data']);
        $this->assertEquals(0, $result['more']);
    }

    public function testHaveContentLength()
    {
        $data = "GET / HTTP/1.1\r\n";
        $data .= "Content-Length: 1";
        $data .= "\r\n\r\n1";
        $result = Http::idealUnpacking($data);
        $this->assertEquals(1, $result['content_length']);
        $this->assertEquals('1', $result['body']);
        $this->assertEquals('', $result['unknow_data']);
        $this->assertEquals(0, $result['more']);
    }

    public function testHaveContentLengthAndHaveUnknowData()
    {
        $data = "GET / HTTP/1.1\r\n";
        $data .= "Content-Length: 1";
        $data .= "\r\n\r\nabc";
        $result = Http::idealUnpacking($data);
        $this->assertEquals(1, $result['content_length']);
        $this->assertEquals('a', $result['body']);
        $this->assertEquals('bc', $result['unknow_data']);
        $this->assertEquals(0, $result['more']);
    }

    public function testHaveContentLengthAndNotEnoughData()
    {
        $data = "GET / HTTP/1.1\r\n";
        $data .= "Content-Length: 10";
        $data .= "\r\n\r\n1234567";
        $result = Http::idealUnpacking($data);
        $this->assertEquals(10, $result['content_length']);
        $this->assertEquals('1234567', $result['body']);
        $this->assertEquals('', $result['unknow_data']);
        $this->assertEquals(3, $result['more']);
    }

    public function testNotEnoughDataInNormalPostMethod()
    {
        $data = "POST / HTTP/1.1\r\n";
        $data .= "Content-Length: 5";
        $data .= "\r\n\r\nabc";
        $result = Http::idealUnpacking($data);
        $this->assertEquals(5, $result['content_length']);
        $this->assertEquals('abc', $result['body']);
        $this->assertEquals('', $result['unknow_data']);
        $this->assertEquals(2, $result['more']);
    }

    public function testNotEnoughDataInMultipartFormData()
    {
        $pl = str_repeat('1', 20);
        $data = HttpTube::buildUploadPostData($pl, 'www.example.com', 80);
        $dataHead = substr($data, 0, strlen($data) - 1);
        $result = Http::idealUnpacking($dataHead);
        $this->assertEquals(-1, $result['content_length']);
        $this->assertEquals('', $result['body']);
        $this->assertEquals($dataHead, $result['unknow_data']);
        $this->assertEquals(-1, $result['more']);
    }

    public function testNotDataInMultipartFormDataHaveUnknowData()
    {
        $pl = str_repeat('1', 20);
        $data = HttpTube::buildUploadPostData($pl, 'www.example.com', 80) . 'X';
        $result = Http::idealUnpacking($data);
        $this->assertGreaterThan(20, $result['content_length']);
        $this->assertStringContainsString($pl, $result['body']);
        $this->assertEquals('X', $result['unknow_data']);
        $this->assertEquals(0, $result['more']);
    }

    public function testDataInMultipartFormData()
    {
        $pl = str_repeat('1', 20);
        $data = HttpTube::buildUploadPostData($pl, 'www.example.com', 80);
        $result = Http::idealUnpacking($data);
        $this->assertGreaterThan(20, $result['content_length']);
        $this->assertStringContainsString($pl, $result['body']);
        $this->assertEquals('', $result['unknow_data']);
        $this->assertEquals(0, $result['more']);
    }
}
